with Ada.Unchecked_Conversion;

with Win32.Windef;
with Win32.Winbase;

package win32api_interface.memory is

  --  This package contains the bindings to manage the two Win32 APi basic
  --  functions to access a process memory.

  type Memorystatus is new Win32.Winbase.MEMORYSTATUS;

  type Byte is mod 256;
  subtype Array_Length is Integer range 1..1024;

  Semi_Read_Error, Read_Process_Memory_Error : exception;

  --type uinteger is mod 2 ** 32;--Interfaces.C.unsigned_long;

  subtype Process_ID is Win32.DWORD;
  type Process_ID_Array is array (Positive range <>) of Process_ID;

  PSAPI_Handle : Win32.Windef.HINSTANCE := Win32.Winbase.LoadLibrary(
                                           Win32.Addr("PSAPI"&ascii.nul));

  type PROCESS_MEMORY_COUNTERS is record
    cb                         : Win32.DWORD;
    PageFaultCount             : Win32.DWORD;
    PeakWorkingSetSize         : Win32.SIZE_T;
    WorkingSetSize             : Win32.SIZE_T;
    QuotaPeakPagedPoolUsage    : Win32.SIZE_T;
    QuotaPagedPoolUsage        : Win32.SIZE_T;
    QuotaPeakNonPagedPoolUsage : Win32.SIZE_T;
    QuotaNonPagedPoolUsage     : Win32.SIZE_T;
    PagefileUsage              : Win32.SIZE_T;
    PeakPagefileUsage          : Win32.SIZE_T;
  end record;

  subtype SYSTEM_INFO is Win32.Winbase.SYSTEM_INFO;
  subtype MEMORY_BASIC_INFORMATION is Win32.Winnt.MEMORY_BASIC_INFORMATION;

  type GetProcessMemoryInfo_Access is
    access function
    (Process        : Handle;
     ppsmemCounters : System.Address;
     lpcbNeeded     : Win32.DWORD)
    return Win32.BOOL;
  pragma Convention (Stdcall, GetProcessMemoryInfo_Access);
  function Convert is new Ada.Unchecked_Conversion
    (Win32.Windef.FARPROC, GetProcessMemoryInfo_Access);
  GetProcessMemoryInfo : GetProcessMemoryInfo_Access
     := Convert (Win32.Winbase.GetProcAddress(
                   PSAPI_Handle,
                   Win32.Addr("GetProcessMemoryInfo"&ascii.nul)));

  function Read_Process_Memory(Handle: in Win32.Winnt.HANDLE;
                               Target: in Address;
                               Length: in Integer) return string;
  --  Given an access handle from a process and a target address to start
  --  to read from, it returns a Byte_Array with the Length number of bytes
  --  read.

  procedure Write_Process_Memory(Handle: in Win32.Winnt.HANDLE;
                                 Target: in Address;
                                 Value:  in string);
  --  Given an access handle from a process, a target address to start to
  --  write from, and a Byte_Array with the Length number of bytes to write,
  --  it writes those bytes into the specified area.

  function Read_Process_Memory_Ex(Handle: in Win32.Winnt.HANDLE;
                                  Target: in Address;
                                  Length: in Integer) return string;

  function Get_System_Info return SYSTEM_INFO;

  function Virtual_Query_Ex (HProc : in Handle; Addr : in Address)
                                    return MEMORY_BASIC_INFORMATION;

  function Get_Process_Memory_Info (HProc: in Handle) return PROCESS_MEMORY_COUNTERS;
  --  Not finished or ready yet.

  function Global_Memory_Status return MEMORYSTATUS;

end win32api_interface.memory;
